
package com.hlkj.pay.app.ad.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.provider.Aes256EncryptionProvider;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.http.template.OkHttpTemplate;
import com.hlkj.pay.app.ad.IAdStatisticsAppService;
import com.hlkj.pay.app.common.ICommonAppService;
import com.hlkj.pay.config.SmsTemplateProperties;
import com.hlkj.pay.dto.ad.AdOtherConfigDto;
import com.hlkj.pay.dto.ad.ReChargeDto;
import com.hlkj.pay.enums.AdEnum;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.enums.UserEnum;
import com.hlkj.pay.infrastructure.model.ad.AdInfoConfigDO;
import com.hlkj.pay.infrastructure.model.ad.AdInfoDO;
import com.hlkj.pay.infrastructure.model.ad.AdPayOrderDO;
import com.hlkj.pay.infrastructure.model.user.UserCouponDO;
import com.hlkj.pay.infrastructure.model.user.UserDO;
import com.hlkj.pay.infrastructure.model.user.UserTeleChargeOrderDO;
import com.hlkj.pay.service.ad.IAdInfoService;
import com.hlkj.pay.service.user.IUserCouponService;
import com.hlkj.pay.service.user.IUserRechargeService;
import com.hlkj.pay.service.user.IUserService;
import com.hlkj.pay.util.OrderCodeUtil;
import com.hlkj.pay.vo.common.req.SmsSendReq;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/10/24 13:36
 */
@RequiredArgsConstructor
@Slf4j
@Component
public class AdPayOrderHandler {

    private final IAdInfoService adInfoService;

    private final IUserService userService;

    private final IUserCouponService userCouponService;

    private final OkHttpTemplate okHttpTemplate;

    private final AdPayOrderHandlerParams adPayOrderHandlerParams;

    private final OrderCodeUtil orderCodeUtil;

    private final IUserRechargeService userRechargeService;

    private final Aes256EncryptionProvider aes256EncryptionProvider;

    private final ICommonAppService commonAppService;

    private final SmsTemplateProperties smsTemplateProperties;

    private final IAdStatisticsAppService adStatisticsAppService;

    private final AdPayOrderMessageHandler adPayOrderMessageHandler;

    @Value("${hlkj.pay.thirdCharge:false}")
    private boolean thirdCharge;

    /**
     * 支付成功
     * 
     * @param adPayOrderDO
     */
    // @Async("adOrderPaySuccessTaskExecutor")
    public void paySuccess(AdPayOrderDO adPayOrderDO) {
        // 发送统计消息
        adPayOrderMessageHandler.sendAdStatistics(adPayOrderDO.getAdId(), adPayOrderDO.getMchOrderNo(), adPayOrderDO.getPayAmount(), AdEnum.STATISTICS_TYPE.PAY_ORDER,
                adPayOrderDO.getCreateTime());
        // 计算回传
        adStatisticsAppService.processPaySuccessCall(adPayOrderDO);
        // 话费创建用户
        if (!StringUtils.hasText(adPayOrderDO.getPhone())) {
            return;
        }
        SmsSendReq smsSendReq = new SmsSendReq();
        smsSendReq.setTemplateCode(smsTemplateProperties.getAdPaySuccessNotify());
        smsSendReq.setPhone(adPayOrderDO.getPhone());
        commonAppService.sendSms(smsSendReq);

        AdInfoDO adInfoDO = adInfoService.queryById(adPayOrderDO.getAdId());
        if (!AdEnum.AD_TYPE.TELE_BILL.getCode().equals(adInfoDO.getType())) {
            return;
        }
        AdInfoConfigDO adInfoConfigDO = adInfoService.queryConfigByAdId(adPayOrderDO.getAdId());
        UserDO userDO = userService.queryUserByPhone(adPayOrderDO.getPhone());
        if (userDO == null) {
            // 用户不存在 需要进行注册
            userDO = new UserDO();
            userDO.setPhone(adPayOrderDO.getPhone());
            userDO.setType(UserEnum.USER_TYPE.TELE.getCode());
            userDO.setStatus(UserEnum.USER_STATUS.ABLE.getCode());
            userService.saveUser(userDO);
        }
        AdOtherConfigDto otherConfigDto = adInfoConfigDO.getOtherConfigDto();
        if (otherConfigDto == null || CollectionUtils.isEmpty(otherConfigDto.getCouponConfigs())) {
            return;
        }
        List<AdOtherConfigDto.CouponConfig> couponConfigs = otherConfigDto.getCouponConfigs();
        List<UserCouponDO> userCouponDOList = new ArrayList<>();
        for (AdOtherConfigDto.CouponConfig couponConfig : couponConfigs) {
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(couponConfig.getType())) {
                for (int i = 0; i < couponConfig.getNum(); i++) {
                    UserCouponDO userCouponDO = new UserCouponDO();
                    userCouponDO.setCouponId(couponConfig.getCouponId());
                    userCouponDO.setRelationId(adInfoDO.getId());
                    userCouponDO.setRelationType(0);
                    userCouponDO.setUserId(userDO.getId());
                    userCouponDO.setIssuedDate(System.currentTimeMillis());
                    // userCouponDO.setExpiryDate();
                    userCouponDO.setStatus(UserEnum.USER_COUPON_STATUS.NO_USE.getCode());
                    userCouponDOList.add(userCouponDO);
                }
            }
            else {
                boolean sendThirdCharge = false;
                for (int i = 0; i < couponConfig.getNum(); i++) {
                    try {
                        String phone = aes256EncryptionProvider.decryptString(userDO.getPhone());
                        UserTeleChargeOrderDO teleChargeOrderDO = new UserTeleChargeOrderDO();
                        teleChargeOrderDO.setUserId(userDO.getId());
                        teleChargeOrderDO.setPhone(phone);
                        teleChargeOrderDO.setRechargeAmount(couponConfig.getAmount());
                        teleChargeOrderDO.setRemark("支付订单自动充值");
                        teleChargeOrderDO.setChargeNo(orderCodeUtil.orderNo(PayOrderEnums.ORDER_NO_TYPE.RECHARGE_APPLY));
                        // 冲10元话费
                        Map<String, Object> params = adPayOrderHandlerParams.rechargePayParams(adPayOrderDO.getAdId(), otherConfigDto, couponConfig, teleChargeOrderDO);
                        String questData = JsonUtils.toJsonString(params);
                        log.info("话费充值 请求参数:{}", questData);
                        String post;
                        if (thirdCharge) {
                            if (adInfoConfigDO.getCouponUseLimit() != null && adInfoConfigDO.getCouponUseLimit() != 0) {
                                sendThirdCharge = true;
                            }
                        }
                        if (!sendThirdCharge) {
                            post = "{\"errno\":0,\"errmsg\":\"提交成功\",\"data\":{\"id\":262382,\"order_number\":\"HXT241031262382\",\"mobile\":\"18327318860\",\"product_id\":217,\"total_price\":\"11.30\",\"create_time\":1730348737,\"guishu\":\"湖北武汉\",\"title\":\"【轮询】三网小额10元【补差价，有中价移动】三网话费\",\"out_trade_num\":\"C20241031042538599955969\"}}";
                        }
                        else {
                            post = okHttpTemplate.post(otherConfigDto.getUrl(), questData, null);
                        }
                        log.info("话费充值 返回参数:{}", post);
                        ReChargeDto reChargeDto = JsonUtils.parseObject(post, ReChargeDto.class);
                        if ("0".equals(reChargeDto.getErrno())) {
                            teleChargeOrderDO.setState(UserEnum.RECHARGE_STATUS.DOING.getCode());
                            teleChargeOrderDO.setThirdRechargeId(reChargeDto.getData().getOrder_number());
                        }
                        else {
                            teleChargeOrderDO.setState(UserEnum.RECHARGE_STATUS.FAIL.getCode());
                            teleChargeOrderDO.setRemark("支付订单自动充值失败 " + reChargeDto.getErrmsg());
                        }
                        userRechargeService.addRechargeOrder(teleChargeOrderDO);
                    }
                    catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        if (!CollectionUtils.isEmpty(userCouponDOList)) {
            log.info("用户支付成功 送优惠劵 phone:{},couponSize:{}", adPayOrderDO.getPhone(), userCouponDOList.size());
            userCouponService.addUserCouponList(userCouponDOList);
        }

    }

    @Bean(name = "adOrderPaySuccessTaskExecutor")
    public Executor adOrderPaySuccessTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5); // 核心线程数
        executor.setMaxPoolSize(10); // 最大线程数
        executor.setQueueCapacity(100); // 队列容量
        executor.setKeepAliveSeconds(60); // 线程空闲时间
        executor.setThreadNamePrefix("Async-paySuccess-"); // 线程名称前缀
        executor.initialize();
        return executor;
    }

    @Bean(name = "adOrderStatusTaskExecutor")
    public Executor adOrderStatusTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5); // 核心线程数
        executor.setMaxPoolSize(10); // 最大线程数
        executor.setQueueCapacity(100); // 队列容量
        executor.setKeepAliveSeconds(60); // 线程空闲时间
        executor.setThreadNamePrefix("Async-orderStatus-"); // 线程名称前缀
        executor.initialize();
        return executor;
    }
}
